﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using EasyLib.Utils;

namespace EasyLib.Extensions
{
    public static class XMLUtils
    {
        /// <summary>
        /// Load xml document as xelement
        /// </summary>
        public static XElement Load(string filePath)
        {
            if (filePath.IsNullOrBlank())
            {
                throw new ArgumentNullException(filePath, "XML file path is null or empty, please have a check.");
            }
            if (!File.Exists(filePath))
            {
                throw new ArgumentException("File is not exists.", filePath);
            }
            XElement element = XElement.Load(filePath);
            return element;
        }

        #region 针对于XElement的扩展方法
        /// <summary>
        /// 获得下一级的元素中指定名字的元素集合
        /// </summary>
        /// <param name="parentElement">父节点</param>
        /// <param name="name">子节点名称</param>
        /// <returns>代表子节点的xelement</returns>
        public static XElement GetElement(this XElement parentElement, string name)
        {
            return parentElement.Elements().Where(e => e.Name.LocalName == name).FirstOrDefault();
        }

        /// <summary>
        /// 泛型方法，得到指定名称的元素的值
        /// </summary>
        /// <typeparam name="T">元素值类型</typeparam>
        /// <param name="element">代表元素的xelement</param>
        /// <returns>元素的值</returns>
        public static T GetElementValue<T>(this XElement element)
        {
            object value = element.Value;
            return TypeConvertUtils.ConvertType<T>(value);
        }

        /// <summary>
        /// 重载方法, 返回类型为string的指定名称的元素的值
        /// </summary>
        /// <param name="element">代表元素的xelement</param>
        /// <returns>元素的值</returns>
        public static string GetElementValue(this XElement element)
        {
            return element.GetElementValue<string>();
        }

        /// <summary>
        /// 获得元素的子元素的名称集合
        /// </summary>
        /// <param name="element"></param>
        /// <returns></returns>
        public static IList<string> GetElementNames(this XElement element)
        {
            var productNameList = element.Elements().Select(e => e.Name.LocalName).Distinct();
            return productNameList.ToList();
        }

        /// <summary>
        /// 元素中是否有指定名称的子元素
        /// </summary>
        public static bool ContainsElement(this XElement element, string elementName)
        {
            return element.GetElementNames().Contains(elementName);
        }

        /// <summary>
        /// 元素中获取指定名称的属性
        /// </summary>
        public static XAttribute GetAttribute(this XElement element, string attributeName)
        {
            return element.Attributes().Where(x => x.Name.LocalName == attributeName).FirstOrDefault();
        }

        /// <summary>
        /// 泛型方法，得到指定名称的属性的值
        /// </summary>
        public static T GetAttributeValue<T>(this XElement element, string attributeName)
        {
            XAttribute attr = element.GetAttribute(attributeName);
            object value = attr.Value;
            return TypeConvertUtils.ConvertType<T>(value);
        }

        /// <summary>
        ///重载方法, 返回类型为string的指定名称的属性的值 
        /// </summary>
        public static string GetAttributeValue(this XElement element, string attributeName)
        {
            return element.GetAttributeValue<string>(attributeName);
        }

        #endregion
    }

}